package com.zmc.coupon.application.construct.impl;

import com.lmax.disruptor.RingBuffer;
import com.zmc.common.domain.vo.coupon.CouponFeignVo;
import com.zmc.common.domain.vo.coupon.FullReductionFeignVo;
import com.zmc.common.domain.vo.coupon.LadderFeignVo;
import com.zmc.common.domain.resp.coupon.CouponAllFeignResp;
import com.zmc.coupon.application.construct.CouponConstructService;
import com.zmc.coupon.constants.CouponConstant;
import com.zmc.coupon.enums.CouponEnum;
import com.zmc.coupon.infrastructure.bean.vo.CouponHistoryUpdateProducer;
import com.zmc.coupon.infrastructure.entity.*;
import com.zmc.coupon.infrastructure.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author：zmc
 * @Date：2024/12/6 13:03
 */

@Scope("prototype")
@Component
public class CouponConstructServiceImpl implements CouponConstructService {

    private Map<String, CouponAllFeignResp> map;

    @Autowired
    private CouponService couponService;

    @Autowired
    private CouponSkuService couponSkuService;

    @Autowired
    private SkuFullReductionService skuFullReductionService;

    @Autowired
    private SkuLadderService skuLadderService;

    @Autowired
    private CouponHistoryService couponHistoryService;

    @Autowired
    private RingBuffer<CouponHistoryUpdateProducer> couponHistoryUpdateRingBuffer;

    @Override
    public CouponConstructService create(List<String> skuIds) {
        map = new HashMap<>();
        skuIds.forEach(skuId -> {
            CouponAllFeignResp resp = new CouponAllFeignResp();
            resp.setSkuId(skuId);
            map.put(skuId, resp);
        });
        return this;
    }

    @Override
    public CouponConstructService coupon(int type) {
        List<String> skuIds = new ArrayList<>(map.keySet());
        //查找商品是否挂载到优惠卷
        List<CouponSkuEntity> list = couponSkuService.getBySkuIds(skuIds);
        if (CollectionUtils.isEmpty(list)) {
            return this;
        }
        //筛选出商品优惠卷列表
        List<CouponEntity> couponList = couponService.listByIds(list.stream().map(CouponSkuEntity::getCouponId).collect(Collectors.toList()));
        //查找用户挂载到商品列表上的所有有优惠卷记录
        List<Long> couponIds = couponList.stream().map(CouponEntity::getId).collect(Collectors.toList());
        List<CouponHistoryEntity> userHistoryList = couponHistoryService.getUserHistoryList(couponIds);
        LocalDateTime now = LocalDateTime.now();
        //从商品维度找出匹配的优惠卷，即一个商品只能有一个优惠卷，一个优惠卷下可以挂载多个商品
        list.forEach(coupon -> {
            couponList.stream()
                    //过滤出当前卷
                    .filter(item -> Objects.equals(coupon.getCouponId(), item.getId()))
                    //卷是否可用
                    .filter(item -> {
                        if (now.isBefore(item.getEndTime()) && now.isAfter(item.getStartTime())) {
                            return true;
                        }
                        //卷是否过期,若优惠卷已过期，检查优惠卷记录是否未更新
                        if (now.isAfter(item.getEndTime())) {
                            userHistoryList.stream().filter(history -> Objects.equals(history.getCouponId(), item.getId())
                                            && history.getUseType() == CouponEnum.COUPON_USE_TYPE_NOT_USE.getCode())
                                    .findFirst().ifPresent(history -> {
                                        new CouponHistoryUpdateProducer(couponHistoryUpdateRingBuffer, history.getCouponId()).publish();
                                    });
                        }
                        return false;
                    })
                    //卷是否已经发完
                    .filter(item -> item.getReceiveCount() < item.getPublishCount())
                    //当前用户是否符合领取标准
                    .filter(item -> {
                        //用户未领取
                        if (CollectionUtils.isEmpty(userHistoryList)) {
                            return type == 1;
                        }
                        //用户已领取当前卷但未使用
                        long notUserCount = userHistoryList.stream()
                                .filter(user -> user.getCouponId().equals(item.getId()) && skuIds.contains(user.getSkuId()))
                                .filter(user -> user.getUseType() == CouponEnum.COUPON_USE_TYPE_NOT_USE.getCode())
                                .count();
                        if (notUserCount > 0) {
                            return true;
                        }
                        //用户已使用，但没有超过优惠卷领取限制
                        return userHistoryList.stream().filter(user -> user.getCouponId().equals(item.getId())).count() < item.getPerLimit();
                    }).findFirst().ifPresent(item -> {
                        CouponFeignVo couponVo = new CouponFeignVo();
                        couponVo.setCouponId(coupon.getCouponId());
                        //若用户有未使用的卷,则设置
                        userHistoryList.stream().filter(user -> user.getCouponId().equals(item.getId()))
                                .filter(user -> user.getUseType() == CouponEnum.COUPON_USE_TYPE_NOT_USE.getCode() &&
                                        coupon.getSkuId().equals(user.getSkuId()))
                                .findFirst().ifPresent(history -> {
                                    couponVo.setCouponHistoryId(history.getId());
                                });
                        couponVo.setCount(1);
                        couponVo.setMinPoint(item.getMinPoint());
                        couponVo.setAmount(item.getAmount());
                        map.get(coupon.getSkuId()).setCoupon(couponVo);
                    });
        });
        return this;
    }

    @Override
    public CouponConstructService reduction() {
        List<String> skuIds = new ArrayList<>(map.keySet());
        List<SkuFullReductionEntity> list = skuFullReductionService.getBySkuIds(skuIds);
        for (SkuFullReductionEntity entity : list) {
            CouponAllFeignResp resp = map.get(entity.getSkuId());
            if ((resp.getCoupon() != null || resp.getLadder() != null) && CouponConstant.COUPON_NOT_ADD_OTHER.equals(entity.getAddOther())) {
                continue;
            }
            FullReductionFeignVo vo = new FullReductionFeignVo();
            vo.setFullPrice(entity.getFullPrice());
            vo.setReducePrice(entity.getReducePrice());
            resp.setReduction(vo);
        }
        return this;
    }

    @Override
    public CouponConstructService ladder() {
        List<String> skuIds = new ArrayList<>(map.keySet());
        List<SkuLadderEntity> list = skuLadderService.getBySkuIds(skuIds);
        for (SkuLadderEntity entity : list) {
            CouponAllFeignResp resp = map.get(entity.getSkuId());
            if ((resp.getCoupon() != null || resp.getReduction() != null) && CouponConstant.COUPON_NOT_ADD_OTHER.equals(entity.getAddOther())) {
                continue;
            }
            LadderFeignVo vo = new LadderFeignVo();
            vo.setDiscount(entity.getDiscount());
            vo.setFullCount(entity.getFullCount());
            resp.setLadder(vo);
        }
        return this;
    }

    @Override
    public List<CouponAllFeignResp> list() {
        return new ArrayList<>(map.values());
    }
}
